﻿using System;
using CrossLayerCommunication;
using CrossLayerCommunication.FluentValidation;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;

namespace UnitTest
{
    [TestClass]
    public class TestOperationResult
    {
        [TestMethod]
        public void TestCreation()
        {
            Message.AllMessages.Clear();

            CheckOperationResult(OperationResult.OK, expectedOperationWasSuccesfull: true, expectedNumberOfMessages: 0);
            CheckOperationResult(new OperationResult(), expectedOperationWasSuccesfull: true, expectedNumberOfMessages: 0);
            CheckOperationResult(new OperationResult(MessageHelper.CreateOrGetMessage(-1, type: MessageType.Warning), MessageHelper.CreateOrGetMessage(-2, type: MessageType.Info)), expectedOperationWasSuccesfull: true, expectedNumberOfMessages: 2);
            CheckOperationResult(new OperationResult(MessageHelper.CreateOrGetMessage(-2), MessageHelper.CreateOrGetMessage(2)), expectedOperationWasSuccesfull: false, expectedNumberOfMessages: 2);
        }

        [TestMethod]
        public void TestAddMessages()
        {
            Message.AllMessages.Clear();

            IOperationResult operationResult = OperationResult.OK;
            
            operationResult.AddMessages(null);
            CheckOperationResult(operationResult, expectedOperationWasSuccesfull: true, expectedNumberOfMessages: 0);

            operationResult.AddMessages(MessageHelper.CreateOrGetMessage(-1, type: MessageType.Warning));
            CheckOperationResult(operationResult, expectedOperationWasSuccesfull: true, expectedNumberOfMessages: 1);

            operationResult.AddMessages(MessageHelper.CreateOrGetMessage(-1));
            CheckOperationResult(operationResult, expectedOperationWasSuccesfull: true, expectedNumberOfMessages: 1);

            operationResult.AddMessages(MessageHelper.CreateOrGetMessage(-2));
            CheckOperationResult(operationResult, expectedOperationWasSuccesfull: false, expectedNumberOfMessages: 2);

            operationResult.AddMessages(MessageHelper.CreateOrGetMessage(-3, key: "Key", arguments: new object[2] { "Testing", 1 }));
            CheckOperationResult(operationResult, expectedOperationWasSuccesfull: false, expectedNumberOfMessages: 3);
            IMessage message = operationResult.Messages.FirstOrDefault(item => item.Id == -3);
            Assert.AreEqual("Key", message.Key);
            Assert.AreEqual(2, message.Params.Length);
            Assert.AreEqual("Testing", message.Params[0]);
            Assert.AreEqual(1, message.Params[1]);
        }

        [TestMethod]
        public void TestCreationWithData()
        {          
            Message.AllMessages.Clear();

            CheckOperationResult(new OperationResult<string>(), expectedOperationWasSuccesfull: true, expectedNumberOfMessages: 0);
            CheckOperationResult(new OperationResult<string>(MessageHelper.CreateOrGetMessage(-1, type: MessageType.Warning), MessageHelper.CreateOrGetMessage(-2, type: MessageType.Info)), expectedOperationWasSuccesfull: true, expectedNumberOfMessages: 2);
            CheckOperationResult(new OperationResult<string>(MessageHelper.CreateOrGetMessage(-2), MessageHelper.CreateOrGetMessage(2)), expectedOperationWasSuccesfull: false, expectedNumberOfMessages: 2);
            IOperationResult<string> operationResult = new OperationResult<string>(new IMessage[1] { MessageHelper.CreateOrGetMessage(-3) }.Select(item => item));
            CheckOperationResult(operationResult, expectedOperationWasSuccesfull: false, expectedNumberOfMessages: 1);

            operationResult = new OperationResult<string>("Testing");
            CheckOperationResult(operationResult, expectedOperationWasSuccesfull: true, expectedNumberOfMessages: 0);
            Assert.AreEqual("Testing", operationResult.Data);

            
        }

        [TestMethod]
        public void TestAddFluentValidationResult()
        {
            IOperationResult operationResult = OperationResult.OK;

            operationResult.MergeFluentValidationResult(
                5.FluentValidation(MessageHelper.CreateOrGetMessage(-1)).IsDefault(),
                "Testing".FluentValidation(MessageHelper.CreateOrGetMessage(-2)).IsLengthEqualTo(0)
                );

            CheckOperationResult(operationResult, expectedOperationWasSuccesfull: false, expectedNumberOfMessages: 2);
            Assert.IsNotNull(operationResult.Messages.FirstOrDefault(item => item.Id == -1));
            Assert.IsNotNull(operationResult.Messages.FirstOrDefault(item => item.Id == -2));
        }

        [TestMethod]
        public void TestAddFluentValidationResultWithData()
        {
            IOperationResult<string> operationResult = new OperationResult<string>("Testing");

            operationResult.MergeFluentValidationResult(
                5.FluentValidation(MessageHelper.CreateOrGetMessage(-1)).IsDefault(),
                "Testing".FluentValidation(MessageHelper.CreateOrGetMessage(-2)).IsLengthEqualTo(0)
                );

            CheckOperationResult(operationResult, expectedOperationWasSuccesfull: false, expectedNumberOfMessages: 2);
            Assert.IsNotNull(operationResult.Messages.FirstOrDefault(item => item.Id == -1));
            Assert.IsNotNull(operationResult.Messages.FirstOrDefault(item => item.Id == -2));
        }

        internal static void CheckOperationResult(IOperationResult operationResult, bool expectedOperationWasSuccesfull, int expectedNumberOfMessages)
        {
            Assert.AreEqual(expectedOperationWasSuccesfull, operationResult.WasSuccessful);
            Assert.AreEqual(expectedNumberOfMessages, operationResult.Messages.Count());
        }
    }
}
